/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bff.core.action.retrieve;

import com.inspur.edp.bef.api.parameter.retrieve.RetrieveParam;
import com.inspur.edp.bef.auditconfig.api.BefAuditConfigService;
import com.inspur.edp.bef.auditconfig.entity.BefAuditConfig;
import com.inspur.edp.bef.auditconfig.entity.BefAuditConfigItem;
import com.inspur.edp.bff.api.manager.assembler.IAssemblerManager;
import com.inspur.edp.bff.api.manager.context.DataMapperContext;
import com.inspur.edp.bff.api.manager.context.RetrieveContext;
import com.inspur.edp.bff.core.action.query.AuditUtils;
import com.inspur.edp.bff.core.manager.ActionConstant;
import com.inspur.edp.bff.spi.AbstractFSAction;
import com.inspur.edp.cef.entity.entity.IEntityData;
import io.iec.edp.caf.audit.api.data.AuditType;
import io.iec.edp.caf.audit.api.data.EventResultType;
import io.iec.edp.caf.audit.api.data.GspAudit;
import io.iec.edp.caf.audit.api.manager.GspAuditManager;
import io.iec.edp.caf.boot.context.CAFContext;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import lombok.var;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class MultiRetrieveAction extends AbstractFSAction<List<IEntityData>> {

    private java.util.ArrayList<String> dataIds;
    private RetrieveParam param;


    public MultiRetrieveAction(java.util.ArrayList<String> dataIds, RetrieveParam param) {
        this.dataIds = dataIds;
        this.param = param;
    }

    @Override
    protected void execute() {
        IAssemblerManager assemblyManager = getContext().getAssemblerManager();
        RetrieveContext retrieveContext = new RetrieveContext();
        retrieveContext.setDataIds(dataIds);
        retrieveContext.setParam(param);
        //① BeforeRetrieve
        assemblyManager.getRetrieveAssembler().doBeforeRetrieve(getContext(), retrieveContext);

        //② DoRetrieve
        assemblyManager.getRetrieveAssembler().doRetrieve(getContext(), retrieveContext);
        if (retrieveContext.getRetrieveData() == null || retrieveContext.getRetrieveData().size() < 1) {
            setResult(null);
            return;
        }
        //③ DataMapping
        DataMapperContext mapperContext = new DataMapperContext();
        mapperContext.setSourceData(retrieveContext.getRetrieveData());

        ArrayList<IEntityData> vmDatas = assemblyManager.
                getDataMapperAssembler().doDataMapping2Vo(getContext(), mapperContext);
        retrieveContext.setRetrieveResult(vmDatas);
        //④ AfterRetrieve
        assemblyManager.getRetrieveAssembler().doAfterRetrieve(getContext(), retrieveContext);
        setResult(vmDatas);
        auditLog(retrieveContext.getRetrieveData());
    }

    private void auditLog(HashMap<String, ArrayList<IEntityData>> vmDatas) {
        if (getContext().getVoId() == null || getContext().getVoId().equals(""))
            return;

        List<BefAuditConfig> list = SpringBeanUtils.getBean(BefAuditConfigService.class).getBefAuditConfigsByVoId(this.getContext().getVoId());
        if (list == null || list.size() == 0)
            return;
        for (BefAuditConfig config : list) {
            auditItem(config, vmDatas);
        }
    }

    private void auditItem(BefAuditConfig auditConfig, HashMap<String, ArrayList<IEntityData>> vmDatas) {
        if (auditConfig.getConfigItems() == null || auditConfig.getConfigItems().size() == 0)
            return;
        for (var item : auditConfig.getConfigItems()) {
            if (!ActionConstant.RetrieveActionId.equals(item.getTargetVoActionId()))
                continue;
            GspAudit gspAudit = new GspAudit();
            gspAudit.setId(UUID.randomUUID().toString());
            gspAudit.setCategoryId(item.getAuditTypeId());
            gspAudit.setEventId(item.getAuditEventId());
            gspAudit.setDateTime(new Date());
            gspAudit.setType(AuditType.message);
            gspAudit.setEventResult(EventResultType.success);
            gspAudit.setGspAuditData(new ArrayList<>());
            gspAudit.setDescription(item.getAuditMessage().getAuditMessage());
            setAuditMessage(gspAudit, item, vmDatas);
            if (CAFContext.current.getFrameworkContext() != null) {
                gspAudit.setFunctionId(CAFContext.current.getFrameworkContext().getFuncId());
                gspAudit.setFunctionCode(CAFContext.current.getFrameworkContext().getFuncCode());
                if (CAFContext.current.getFrameworkContext().getItems().containsKey("menuName"))
                    gspAudit.setFunctionName(
                            String.valueOf(
                                    CAFContext.current.getFrameworkContext().getItems().get("menuName")));
            }
            SpringBeanUtils.getBean(GspAuditManager.class).addAuditSync(gspAudit);
        }
    }

    private void setAuditMessage(GspAudit gspAudit, BefAuditConfigItem item,
                                 HashMap<String, ArrayList<IEntityData>> vmDatas) {
        Map<String, List<String>> auditMessageDataFields = new HashMap<>();
        Map<String, Map<String, List<String>>> childAuditMessageDataFields = new HashMap<>();
        AuditUtils.getAuditMessageField(gspAudit, item, auditMessageDataFields, childAuditMessageDataFields);
        for (Map.Entry<String, ArrayList<IEntityData>> data : vmDatas.entrySet()) {
            if (data.getValue() != null)
                for (IEntityData dataItem : data.getValue())
                    AuditUtils.addAuditMessageFieldValue(dataItem, "", auditMessageDataFields, childAuditMessageDataFields, this.getContext());
        }
        AuditUtils.setAuditMessage(gspAudit, auditMessageDataFields, childAuditMessageDataFields);
    }
}
